﻿using BCCommon;
using BCCommon.Enums;
using BCData.Sim.Admin.TreePermission;
using BCDto.Common.TreeNode;
using BCDto.Sim.Admin.TreePermission;
using BCEntity.Common.EntityNameConst;
using BCEntity.Sim.Admin.TreePermission;
using BCService.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace BCService.Sim.Admin.TreePermission
{
    public class TreePermissionConfigService : ITreePermissionConfigService
    {
        private readonly ITreePermissionConfigData treePermissionConfigData;
        private readonly ITreePermissionRecordData treePermissionRecordData;
        private readonly IDatabaseContext databaseContext;
        private readonly IRedisService redisService;
        private readonly string key = string.Format("{0}", EntityNameConst.TreePermissionConfigEntity);

        public TreePermissionConfigService(ITreePermissionConfigData treePermissionConfigData,
            ITreePermissionRecordData treePermissionRecordData,
            IDatabaseContext databaseContext,
            IRedisService redisService)
        {
            this.treePermissionConfigData = treePermissionConfigData;
            this.treePermissionRecordData = treePermissionRecordData;
            this.databaseContext = databaseContext;
            this.redisService = redisService;
        }

        public TreePermissionConfigDto Add(TreePermissionConfigRequestDto requestDto)
        {
            if (string.IsNullOrWhiteSpace(requestDto.PermissionCode.Trim()))
            {
                throw new ArgumentException("此权限码为必填项");
            }
            if (string.IsNullOrWhiteSpace(requestDto.PermissionPathCode.Trim()))
            {
                throw new ArgumentException("此权限路径码不能为空");
            }
            string permissionCode = requestDto.PermissionPathCode;
            while (permissionCode.IndexOf('.') > -1)
            {
                permissionCode = permissionCode.Replace(".","_");
            }
            string permissionPathCode = string.Format("{0}.{1}", requestDto.PermissionPathCode, requestDto.PermissionCode);
            if (this.treePermissionConfigData.CheckExists(string.Format("{0}_{1}", permissionCode, requestDto.PermissionCode)).Result)
            {
                throw new ArgumentException("此权限码已存在");
            }
            if (string.IsNullOrWhiteSpace(requestDto.PermissionName.Trim()))
            {
                throw new ArgumentException("此权限名称为必填项");
            }
            
            int level = 0;
            var entity = requestDto.As<TreePermissionConfigEntity>();
            entity.CreateTime = DateTime.Now;
            entity.PermissionCode = string.Format("{0}_{1}", permissionCode, requestDto.PermissionCode);

            if (permissionPathCode.IndexOf(".") > -1)
            {
                level = permissionPathCode.Split(".").Length - 1;
                entity.ParentPermissionPathCode = requestDto.PermissionPathCode;
            }
            else
            {
                entity.ParentPermissionPathCode = string.Empty;
            }

            entity.PermissionPathCode = permissionPathCode;
            entity.PermissionLevel = level;
            if(entity.PermissionType == PermissionType.Button.ToString())
            {
                var parentEntity = this.treePermissionConfigData.GetEntityAsync(entity.ParentPermissionPathCode).Result;
                entity.PagePathCode = parentEntity.PagePathCode;
            }
            //entity.PagePathCode = requestDto.PermissionPathCode.Replace(".", "/");
            var result = this.treePermissionConfigData.InsertAsync(entity).GetAwaiter().GetResult().As<TreePermissionConfigDto>();
            if (result != null)
            {
                this.redisService.DeleteMultipleKey(key, false);
            }
            return result;
        }

        public void UpdateShow(long treePermissionConfigId, bool isShow)
        {
            if(this.treePermissionConfigData.UpdateShow(treePermissionConfigId, isShow).GetAwaiter().GetResult()<=0)
            {
                throw new ArgumentException("修改显示权限失败!");
            }
        }

        public void Delete(long treePermissionConfigId)
        {
            var result = this.treePermissionConfigData.GetEntityAsync(treePermissionConfigId).Result;
            if (result == null)
            {
                throw new ArgumentException("此权限配置不存在");
            }
            databaseContext.BeginTransaction();
            this.treePermissionConfigData.Delete(treePermissionConfigId).GetAwaiter().GetResult();
            this.treePermissionRecordData.Delete(treePermissionConfigId).GetAwaiter().GetResult();
            databaseContext.Commit();
            this.redisService.DeleteMultipleKey(key, false);
        }

        public IEnumerable<TreePermissionConfigDto> GetList(string permissionName, string permissionCode, string permissionPathCode, string parentPermissionPathCode)
        {
            return this.treePermissionConfigData.GetList(permissionName, permissionCode, permissionPathCode, parentPermissionPathCode).Result.As<IEnumerable<TreePermissionConfigDto>>();
        }

        public List<TreeNodeDto<TreePermissionConfigDto>> GetTreePermission()
        {
            List<TreePermissionConfigEntity> configList = this.treePermissionConfigData.GetList(null, null, null, null).Result.ToList();

            List<TreeNodeDto<TreePermissionConfigDto>> list = new List<TreeNodeDto<TreePermissionConfigDto>>();
            var rootPermissions = configList.Where(p => p.PermissionLevel == 0).OrderBy(p => p.PermissionOrder);

            foreach (var item in rootPermissions)
            {
                var root = new TreeNodeDto<TreePermissionConfigDto>();
                root.Title = item.PermissionName;
                root.Key = item.PermissionPathCode;
                root.SourceData = item.As<TreePermissionConfigDto>();
                root.IsLeaf = false;
                root.Expanded = true;
                root.Children = GetTreeNodes(item.As<TreePermissionConfigDto>(), configList.As<IEnumerable<TreePermissionConfigDto>>().Where(p => p.PermissionType == PermissionType.Menu));
                list.Add(root);
            }
            return list;
        }

        private List<TreeNodeDto<TreePermissionConfigDto>> GetTreeNodes(TreePermissionConfigDto parentConfig, IEnumerable<TreePermissionConfigDto> source)
        {
            List<TreeNodeDto<TreePermissionConfigDto>> children = new List<TreeNodeDto<TreePermissionConfigDto>>();

            if (source.Any(p => p.ParentPermissionPathCode.Equals(parentConfig.PermissionPathCode)))
            {
                var list = source.Where(p => p.ParentPermissionPathCode.Equals(parentConfig.PermissionPathCode));
                foreach (var item in list)
                {
                    var child = new TreeNodeDto<TreePermissionConfigDto>();
                    child.Title = item.PermissionName;
                    child.Key = item.PermissionPathCode;
                    child.SourceData = item.As<TreePermissionConfigDto>();
                    child.Expanded = true;
                    child.Children = GetTreeNodes(item, source);
                    child.IsLeaf = child.Children.Count == 0;
                    children.Add(child);
                }
            }
            return children;
        }

        public PageableList<TreePermissionConfigDto> Query(string permissionName, string permissionCode, string permissionPathCode, string parentPermissionPathCode, bool? ascending, int pageIndex, int pageSize)
        {
            var (data, dataCount) = this.treePermissionConfigData.QueryAsync(permissionName, permissionCode, permissionPathCode, parentPermissionPathCode, ascending, pageIndex, pageSize).Result;
            return new PageableList<TreePermissionConfigDto>()
            {
                Items = data.As<List<TreePermissionConfigDto>>(),
                Count = dataCount,
                PageIndex = pageIndex,
                PageSize = pageSize
            };
        }

        public TreePermissionConfigDto Update(long treePermissionConfigId, TreePermissionConfigRequestDto requestDto)
        {
            var result = this.treePermissionConfigData.GetEntityAsync(treePermissionConfigId).Result;
            if (result == null)
            {
                throw new ArgumentException("此权限配置不存在");
            }
            if (string.IsNullOrWhiteSpace(requestDto.PermissionName.Trim()))
            {
                throw new ArgumentException("此权限名称为必填项");
            }
            if (string.IsNullOrWhiteSpace(requestDto.PermissionCode.Trim()))
            {
                throw new ArgumentException("此权限码为必填项");
            }
            if (string.IsNullOrWhiteSpace(requestDto.PermissionPathCode.Trim()))
            {
                throw new ArgumentException("此权限路径码不能为空");
            }
            string permissionCode = requestDto.PermissionPathCode;
            while (permissionCode.IndexOf('.') > -1)
            {
                permissionCode = permissionCode.Replace(".", "_");
            }
            string permissionPathCode = string.Format("{0}.{1}", requestDto.PermissionPathCode, requestDto.PermissionCode);
            string newPermissionCode = string.Format("{0}_{1}", permissionCode, requestDto.PermissionCode);
            if (result.PermissionCode.ToLower() != newPermissionCode.ToLower())
            {
                if (this.treePermissionConfigData.CheckExists(newPermissionCode).Result)
                {
                    throw new ArgumentException("此权限编码已存在");
                }
            }
            
            var entity = requestDto.As<TreePermissionConfigEntity>();
            entity.TreePermissionConfigId = treePermissionConfigId;
            entity.PermissionCode = string.Format("{0}_{1}", permissionCode, requestDto.PermissionCode);

            int level = 0;
            if (permissionPathCode.IndexOf(".") > -1)
            {
                level = permissionPathCode.Split(".").Length - 1;
                entity.ParentPermissionPathCode = requestDto.PermissionPathCode;
            }
            else
            {
                entity.ParentPermissionPathCode = string.Empty;
            }
            entity.PermissionPathCode = permissionPathCode;
            entity.PermissionLevel = level;
            if (entity.PermissionType == PermissionType.Button.ToString())
            {
                var parentEntity = this.treePermissionConfigData.GetEntityAsync(entity.ParentPermissionPathCode).Result;
                entity.PagePathCode = parentEntity.PagePathCode;
            }
            result = this.treePermissionConfigData.Update(entity).GetAwaiter().GetResult();

            if (result != null)
            {
                this.redisService.DeleteMultipleKey(key, false);
            }
            return result.As<TreePermissionConfigDto>();
        }
    }
}
